# LeetCode 20、有效的括号

# 一、题目描述

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  • 1、左括号必须用相同类型的右括号闭合。
  • 2、左括号必须以正确的顺序闭合。

# 二、题目解析

有效的括号满足以下几个条件:

  • 1、字符串的长度一定是偶数。
  • 2、括号的匹配遵循右括号和最近的一个左括号进行匹配,它们匹配成功才有可能是有效的括号

# 三、参考代码

# 1、Java 代码

// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 有效的括号( LeetCode 20 ):https://leetcode-cn.com/problems/valid-parentheses
class Solution {
    
    public boolean isValid(String s) {
      
        // 当字符串长度为奇数的时候,属于无效情况,直接返回 false
  if (s.length() % 2 == 1) {
             // 无效情况,返回 false
       return false;
    }
       
     //构建一个栈,用来存储括号
        Stack<Character> stack = new Stack<Character>();
        
        // 把字符串转换为数组的形式,方便获取字符串中的每个字符
        char charArray[] = s.toCharArray();
        
        // 遍历字符串数组中的所有元素
        for( int i = 0 ; i < charArray.length ; i++){
            
            // 获取此时的字符
            char c = charArray[i];   
            
            // 如果字符为左括号 ( ,那么就在栈中添加对左括号 (
            if(c == '('){
               
               // 添加对左括号 (
               stack.push('(');

             // 如果字符为左括号 [ ,那么就在栈中添加对左括号 [
            }else if(c == '['){

               // 添加对应的右括号 ]
               stack.push('[');

             // 如果字符为左括号 { ,那么就在栈中添加对左括号 {
            }else if( c == '{'){

               // 添加对应的右括号 }
               stack.push('{');

               // 否则的话,说明此时 c 是 )] } 这三种符号中的一种
            }else {
               
               // 如果栈已经为空,而现在遍历的字符 c 是 )] } 这三种符号中的一种
               // 找不到可以匹配的括号,返回 false
               // 比如这种情况  }{,直接从右括号开始,此时栈为空
               if(stack.isEmpty()) return false;
               
               // 如果栈不为空,获取栈顶元素
               char top = stack.peek();

               // 将栈顶元素和此时的元素 c 进行比较,如果相同,则将栈顶元素移除
               if( top == '(' && c == ')' || top == '[' && c == ']' || top == '{' && c == '}' ){
                   // 移除栈顶元素
                   stack.pop();
               }else{
                   // 如果不相同,说明不匹配,返回 false
                   return false;
               }
 
            }

        }
        
        // 遍历完整个字符数组,判断栈是否为空
        // 如果栈为空,说明字符数组中的所有括号都是闭合的
        // 如果栈为空,说明有未闭合的括号
        return stack.isEmpty();
    }
}

# **2、**C++ 代码

// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 有效的括号( LeetCode 20 ):https://leetcode-cn.com/problems/valid-parentheses
class Solution {
public:
    bool isValid(string s) {
        // 当字符串长度为奇数的时候,属于无效情况,直接返回 false
        if (s.size() % 2 == 1) {
             // 无效情况,返回 false
             return false;
        }
       
        //构建一个栈,用来存储括号
        stack<char> stk ;
        
        // 遍历字符串数组中的所有元素
        for( int i = 0 ; i < s.size() ; i++){
            
            // 获取此时的字符
            char c = s[i];   
            
            // 如果字符为左括号 ( ,那么就在栈中添加对左括号 (
            if(c == '('){
               
               // 添加对左括号 (
               stk.push('(');

             // 如果字符为左括号 [ ,那么就在栈中添加对左括号 [
            }else if(c == '['){

               // 添加对应的右括号 ]
               stk.push('[');

             // 如果字符为左括号 { ,那么就在栈中添加对左括号 {
            }else if( c == '{'){

               // 添加对应的右括号 }
               stk.push('{');

               // 否则的话,说明此时 c 是 )] } 这三种符号中的一种
            }else {
               
               // 如果栈已经为空,而现在遍历的字符 c 是 )] } 这三种符号中的一种
               // 找不到可以匹配的括号,返回 false
               // 比如这种情况  }{,直接从右括号开始,此时栈为空
               if(stk.empty()) return false;
               
               // 如果栈不为空,获取栈顶元素
               char top = stk.top();

               // 将栈顶元素和此时的元素 c 进行比较,如果相同,则将栈顶元素移除
               if( top == '(' && c == ')' || top == '[' && c == ']' || top == '{' && c == '}' ){
                   // 移除栈顶元素
                   stk.pop();
               }else{
                   // 如果不相同,说明不匹配,返回 false
                   return false;
               }
 
            }

        }
        
        // 遍历完整个字符数组,判断栈是否为空
        // 如果栈为空,说明字符数组中的所有括号都是闭合的
        // 如果栈为空,说明有未闭合的括号
        return stk.empty();

    }
};

# 3、Python 代码

# 登录 AlgoMooc 官网获取更多算法图解
# https://www.algomooc.com
# 作者:程序员吴师兄
# 代码有看不懂的地方一定要私聊咨询吴师兄呀
# // 有效的括号( LeetCode 20 ):https://leetcode-cn.com/problems/valid-parentheses
class Solution:
    def isValid(self, s: str) -> bool:
        # 当字符串长度为奇数的时候,属于无效情况,直接返回 False
        if len(s) % 2 == 1:
             # 无效情况,返回 False
             return False
        
       
        # 构建一个栈,用来存储括号
        stack = list()

        
        # 遍历字符串数组中的所有元素
        for c in s : 
            
            # 如果字符为左括号 ( ,那么就在栈中添加对左括号 (
            if c == '(' :
               
               # 添加对左括号 (
               stack.append('(')

             # 如果字符为左括号 [ ,那么就在栈中添加对左括号 [
            elif c == '[' :

               # 添加对应的右括号 ]
               stack.append('[')

             # 如果字符为左括号 { ,那么就在栈中添加对左括号 {
            elif c == '{' :

               # 添加对应的右括号 }
               stack.append('{')

               # 否则的话,说明此时 c 是 )] } 这三种符号中的一种
            else :
               
               # 如果栈已经为空,而现在遍历的字符 c 是 )] } 这三种符号中的一种
               # 找不到可以匹配的括号,返回 False
               # 比如这种情况  }{,直接从右括号开始,此时栈为空
               if not stack : 
                  return False
               
               # 如果栈不为空,获取栈顶元素
               top = stack[-1]

               # 将栈顶元素和此时的元素 c 进行比较,如果相同,则将栈顶元素移除
               if (top == '(' and c == ')' ) or (top == '[' and c == ']' ) or (top == '{' and c == '}')  :
                    # 移除栈顶元素
                    stack.pop()
               else :
                   # 如果不相同,说明不匹配,返回 False
                   return False

        
        # 遍历完整个字符数组,判断栈是否为空
        # 如果栈为空,说明字符数组中的所有括号都是闭合的
        # 如果栈为空,说明有未闭合的括号
        return not stack

# 四、复杂度分析

时间复杂度:O(n),其中 n 是字符串 s 的长度。

空间复杂度:O(n+∣Σ∣),其中 Σ 表示字符集,本题中字符串只包含 6 种括号,|Σ| =6。栈中的字符数量为 O(n),而哈希表使用的空间为 O(∣Σ∣),相加即可得到总空间复杂度。